Backlog API を使って Backlog に課題を大量登録してみた
こんにちは、リサリサです。
Backlog に大量の課題を一括登録したので記事にしてみます。
やりたいこと
Backlog に大量の課題を一括追加したい。100個くらい……
issue.csv に追加したい内容の一覧を作れば、それを一括で課題登録できるようにしてみました。
Backlog は登録の際、選択肢の項目を全て ID で登録しないといけません。優先度なら、高でななく2など。それを考えながら一覧を作成すると面倒なので、高から2への変換をした上で、一括登録できるようにしました。issue.csv には、高と記載して大丈夫です。(そのために事前に get_id_list.py で id_list.json を作成しています。こちらは初回と、カテゴリ追加などあった際に実行して頂ければ OK です。)
やってみた
実行環境
Python 3.8.0
準備① APIキーの発行
Backlogの認証は、APIキーを利用する場合とOAuthを利用する場合の2通りがあります。今回はAPIキーを用いてAPIの操作を行います。
APIキーは、[個人設定]->[API]から、「登録」ボタンを押すことで発行できます。発行後は、下の画面にAPIキーが表示されるので、これを用いてAPIの操作を行います。
準備② スペースキー、プロジェクトIDを取得
スペースキー
バックログのサブドメインに使われているものです。
xxx.backlog.jp
プロジェクトID
プロジェクトキーかと思いきや、ちょっと違って自動採番の数字になります。
「プロジェクト設定」のURLを見ると記載があります。
https://xxx.backlog.jp/EditProject.action?project.id=1234567890
準備③ IDリストを取得
Backlog API から課題を登録する場合、画面から登録できる「優先度」、「カテゴリー」、「担当者」など、全て ID で登録する必要があります。
それぞれ頑張ると「プロジェクト設定」などからも取得できるのですが、なかなか大変だったので、API でまとめて取得してみました。以下のpythonを実行すると、同ディレクトリに id_list.jsonが作成され、そこに各ID情報が出力されます。
APIキー、スペースキー、プロジェクトIDには、準備①②で取得したキーを記載してください。
import requests import csv import json API_KEY = 'APIキー' SPACE_KEY = 'スペースキー' PROJECT_ID = 'プロジェクトID' BASE_URL = f"https://{SPACE_KEY}.backlog.jp/api/v2" def get_id(url): params = { 'apiKey': API_KEY, } r = requests.get(url, params=params) r.raise_for_status() return json.loads(r.text) # csvのタイトル output = {} print('・issueTypeId(課題の種別のID)用') # 種別一覧の取得 # https://developer.nulab.com/ja/docs/backlog/api/2/get-issue-type-list/# # /api/v2/projects/:projectIdOrKey/issueTypes datas = get_id(f"{BASE_URL}/projects/{PROJECT_ID}/issueTypes") output['issueTypeId'] = {} for data in datas: output['issueTypeId'][data['name']] = data['id'] print(f"{data['id']}:{data['name']}") print('・assigneeId(課題の担当者のID)用') # プロジェクトユーザー一覧の取得 # https://developer.nulab.com/ja/docs/backlog/api/2/get-project-user-list/# # /api/v2/projects/:projectIdOrKey/users datas = get_id(f"{BASE_URL}/projects/{PROJECT_ID}/users") output['assigneeId'] = {} for data in datas: output['assigneeId'][data['name']] = data['id'] print(f"{data['id']}:{data['name']}") print('・categoryId(課題のカテゴリーのID)用') # カテゴリー一覧の取得 # https://developer.nulab.com/ja/docs/backlog/api/2/get-category-list/# # /api/v2/projects/:projectIdOrKey/categories datas = get_id(f"{BASE_URL}/projects/{PROJECT_ID}/categories") output['categoryId[]'] = {} for data in datas: output['categoryId[]'][data['name']] = data['id'] print(f"{data['id']}:{data['name']}") print('・versionId(課題の発生バージョンのID)、milestoneId(課題のマイルストーンのID)用') # バージョン(マイルストーン)一覧の取得 # https://developer.nulab.com/ja/docs/backlog/api/2/get-version-milestone-list/# # /api/v2/projects/:projectIdOrKey/versions datas = get_id(f"{BASE_URL}/projects/{PROJECT_ID}/versions") output['versionId'] = {} output['milestoneId'] = {} for data in datas: output['versionId'][data['name']] = data['id'] output['milestoneId'][data['name']] = data['id'] print(f"{data['id']}:{data['name']}") print('・priorityId(課題の優先度のID)用') # 優先度一覧の取得 # https://developer.nulab.com/ja/docs/backlog/api/2/get-priority-list/# # /api/v2/priorities datas = get_id(f"{BASE_URL}/priorities") output['priorityId'] = {} for data in datas: output['priorityId'][data['name']] = data['id'] print(f"{data['id']}:{data['name']}") # customField_{id}(カスタム属性の値)用 # カスタム属性一覧の取得 # https://developer.nulab.com/ja/docs/backlog/api/2/get-custom-field-list/# # /api/v2/projects/:projectIdOrKey/customFields datas = get_id(f"{BASE_URL}/projects/{PROJECT_ID}/customFields") for data in datas: print(f"・customField_{data['id']}({data['name']})用") output[f"customField_{data['id']}"] = {} for item in data['items']: output[f"customField_{data['id']}"][item['name']] = item['id'] print(f"{item['id']}:{item['name']}") with open('id_list.json', 'w') as f: f.write(json.dumps(output, indent=4, ensure_ascii=False))
id_list.json は以下のようになっています。
{ "issueTypeId": { "Parent Issue": 1074831859, "event": 1074838719, "Task": 1074821804, "Bug": 1074821803, "Request": 1074821805, "Other": 1074821806 }, "assigneeId": { "田中": 1074281901, "木村": 1074201141, "佐藤": 1074121619 }, "categoryId[]": { "外部設計": 1074361053, "内部設計": 1074365061, "プロジェクト管理": 1074371210 }, "versionId": { "第1フェーズ": 1074285907, "第2フェーズ": 1074285906 }, "milestoneId": { "第1フェーズ": 1074285907, "第2フェーズ": 1074285906 }, "priorityId": { "高": 2, "中": 3, "低": 4 }, "customField_1073851824": { "xxxxx": 1, "yyyyy": 1 } }
追加したい課題一覧を作成
Excelやスプレッドシートで一覧を作り、csvに変換します。
項目は以下のパラメーターから必要なものを使ってください。issueTypeId(課題種別),priorityId(優先度),summary(件名)以外の項目であれば、空欄があっても大丈夫ですし、列自体なくても大丈夫です。日付は「yyyy-mm-dd」で記載ください。※複数指定は対応してません。
項目名も選択肢(特に担当者名など)も、機械的にIDに変換して、APIを叩いているだけですので、一言一句間違わずに入力してください…
スプレッドシートの場合は、ファイル⇒ダウンロード⇒csvからcsvに変換できます。
issueTypeId,parentIssueId,priorityId,summary,description,assigneeId,startDate,dueDate,categoryId[],customField_1073853234 Parent Issue,PROJECT-1,中,xxxxの設計,xxxxの設計についての詳細,田中,2022-03-29,2022-04-09,内部設計,xxxxxx Parent Issue,PROJECT-1,中,yyyyの設計,yyyyの設計についての詳細,佐藤,,,内部設計,xxxxxx
id_list.json と同じディレクトリに issue.csv という名前で保存してください。
登録する
id_list.json 、issue.csv と同じディレクトリで実行すると、Backlog に課題登録できます。※バリデーションチェック等していないので、項目名に間違いがあったりするとエラーで落ちます。
APIキー、スペースキー、プロジェクトIDには、準備①②で取得したキーを記載してください。
import requests import csv import json API_KEY = 'APIキー' SPACE_KEY = 'スペースキー' PROJECT_ID = 'プロジェクトID' BASE_URL = f"https://{SPACE_KEY}.backlog.jp/api/v2" def add_issue(payload): url = f"{BASE_URL}/issues" payload['projectId'] = PROJECT_ID params = { 'apiKey': API_KEY, } r = requests.post(url, params=params, data=payload) r.raise_for_status() return r def get_issue_id(issue_key): url = f"{BASE_URL}/issues/{issue_key}" params = { 'apiKey': API_KEY, } r = requests.get(url, params=params, data=payload) r.raise_for_status() print('get_issue') return json.loads(r.text)["id"] # idリストを取得 with open('id_list.json') as f: id_list = json.load(f) # 親課題登録用のidリスト issue_id_list = {} with open('issue.csv') as f: reader = csv.DictReader(f) for r in reader: payload = {} print(r) # 選択肢⇒idへ変換 for k, v in r.items(): # 親課題だけidを取得するためにget issueが必要 if k == 'parentIssueId': if not v in issue_id_list: issue_id_list[v] = get_issue_id(v) payload[k] = issue_id_list[v] else: if v: if k in id_list: payload[k] = id_list[k][v] else: payload[k] = v print(payload) # 課題登録 add_issue(payload)
画面から追加したのと同じように、課題の追加ができました。
最後に
大量の課題追加が必要な誰かのお役に立てれば幸いです。